package edu.uclm.esi.tysweb.ajedrez.websockets;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import edu.uclm.esi.tysweb.ajedrez.dominio.GestorAjedrez;
import edu.uclm.esi.tysweb.ajedrez.dominio.Jugador;
import edu.uclm.esi.tysweb.ajedrez.dominio.Reto;
import edu.uclm.esi.tysweb.ajedrez.dominio.Tablero;
import edu.uclm.esi.tysweb.ajedrez.dominio.mensajes.MensajeDesconexion;
import edu.uclm.esi.tysweb.ajedrez.dominio.mensajes.MensajeError;

@ServerEndpoint(value = "/notificador/notificador", configurator = GetHttpSessionConfigurator.class)
public class Cliente {
	private Session session;
	private HttpSession httpSession;
	private Jugador jugador;

	private static Hashtable<String, Cliente> clientes=new Hashtable<String, Cliente>();
	
	public Cliente() {
	}
	
	public Cliente(Session session, HttpSession httpSession, Jugador jugador) {
		super();
		this.session = session;
		this.httpSession = httpSession;
		this.jugador = jugador;
	}

	@OnOpen
	public void start(Session session, EndpointConfig config) {
		this.session=session;
		this.httpSession=(HttpSession) config.getUserProperties().get(HttpSession.class.getName());
		
		Jugador jugador=(Jugador) httpSession.getAttribute("jugador");
		Cliente cliente= clientes.get(jugador.getEmail());
		if (cliente==null) {
			cliente=new Cliente(session, httpSession, jugador);
			clientes.put(jugador.getEmail(), cliente);
		}
	}
	
	@OnClose
	public void end() {
		if (clientes.contains(this)) {
			 clientes.remove(this);
			 System.out.println(this.jugador.getEmail() + " se ha desconectado");
		}
	}
	
	@OnError
	public void onError(Throwable t) throws Throwable {
		System.out.println("Chat Error: " + t.toString());
	}
	
	@OnMessage
	public void incoming(String msg) throws IOException {
		MensajeError mensajeError;
		JSONObject jo=(JSONObject) JSONValue.parse(msg.toString());
		String tipo=jo.get("tipo").toString();
		if (tipo.equals("reto")) {
			String retador=jo.get("emailRetador").toString();
			String retado=jo.get("emailRetado").toString();
			if (retador.equals(retado)) {
				mensajeError=new MensajeError("No puedes retarte a ti mismo");
				enviar(mensajeError.toJSON().toJSONString());
				return;
			}
			try {
				Reto reto=GestorAjedrez.get().findRetoByRetador(retador);
				if (reto!=null) {
					mensajeError=new MensajeError("Ya tienes un reto pendiente de contestacion");
					enviar(mensajeError.toJSON().toJSONString());
				} else {
					reto=GestorAjedrez.get().retar(retador, retado);
					JSONObject jso=reto.toJSON();
					Cliente cRetado=Cliente.findJugador(retado);
					cRetado.enviar(jso.toJSONString());
				}
			} catch (Exception e) {
				mensajeError=new MensajeError("Se ha producido un error: " + e.getMessage());
				enviar(mensajeError.toJSON().toJSONString());
				return;
			}
			return;
		} 
		if (tipo.equals("contestarReto")) {
			String retador=jo.get("emailRetador").toString();
			String retado=jo.get("emailRetado").toString();
			Boolean respuesta=(Boolean) jo.get("respuesta"); 
			Tablero partida=GestorAjedrez.get().contestarReto(retado, retador, respuesta);
			Cliente cRetado=Cliente.findJugador(retado);
			Cliente cRetador=Cliente.findJugador(retador);
			String mensaje;
			if (partida!=null) {
				mensaje=partida.toJSON().toString();
				cRetado.enviar(mensaje);
			} else {
				Reto reto=GestorAjedrez.get().getReto(retador);
				mensaje=reto.rechazoEnJSON();
			}
			cRetador.enviar(mensaje);
			return;
		} 
		mensajeError=new MensajeError("Has enviado un mensaje desconocido");
		enviar(mensajeError.toJSON().toJSONString());
	}
	
	public void enviar(String msg) throws IOException {
		this.session.getBasicRemote().sendText(msg);
	}

	public static Cliente findJugador(String emailJugador) {
		return Cliente.clientes.get(emailJugador);
	}
	
	public static void broadcast(String msg) {
		Enumeration<Cliente> eClientes=clientes.elements();
		while (eClientes.hasMoreElements()) {
			Cliente cliente = eClientes.nextElement();
			try {
				cliente.enviar(msg);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static void remove(String email) {
		clientes.remove(email);
		MensajeDesconexion md=new MensajeDesconexion(email);
		broadcast(md.toJSON().toString());
	}
	
	
}
